/**
 * 迁移动作：在状态切换前执行（发生在 onExit 之前）。
 * - 可异步；失败不会阻止后续 onExit/onEnter（内部已 try/catch）。
 */
export type TransitionAction<E> = (
  entity: GameEntity,
  event: E
) => void | Promise<void>;

/**
 * 迁移守卫：返回 true 才允许从当前状态按该事件跳转。
 * - 典型用途：冷却、资源条件、死亡保护等。
 */
export type TransitionGuard<E> = (entity: GameEntity, event: E) => boolean;

/**
 * 完整迁移配置（当事件需要 guard/action 时使用）。
 * 否则可使用简写：on: { EVENT: 'targetState' }
 */
export interface TransitionConfig<S extends string, E extends string> {
  /** 目标状态 */
  target: S;
  /** 可选守卫：返回 true 才允许跳转 */
  guard?: TransitionGuard<E>;
  /** 可选动作：在状态实际切换前执行 */
  action?: TransitionAction<E>;
}

/**
 * 状态生命周期钩子：onEnter/onExit。
 * - prev/next：用于区分是初次进入（prev===next===initial）还是普通迁移。
 */
export type StateHook<S extends string> = (
  /** 实体 */
  entity: GameEntity,
  /** 动画控制 */
  motion: GameMotionController<GameEntity>,
  /** 上一状态 */
  prev: S,
  /** 新状态 */
  next: S
) => void | Promise<void>;

/**
 * 单个状态的配置。
 */
export interface StateConfig<S extends string, E extends string> {
  /** 事件迁移表 */
  on?: Partial<Record<E, TransitionConfig<S, E> | S>>;
  /** 进入状态时的回调 */
  onEnter?: StateHook<S>;
  /** 离开状态时的回调 */
  onExit?: StateHook<S>;
  /** 每帧更新时的回调 */
  onUpdate?: (
    /** 实体 */
    entity: GameEntity,
    /** 动画控制 */
    motion: GameMotionController<GameEntity>,
    /** 当前状态 */
    current: S,
    /** 时差 */
    deltaTime: number
  ) => void | Promise<void>;
  /** 是否为终止状态（final）
   * - 如果为true，则该状态不再响应任何事件，update 也应短路（除非你在 onEnter 内部自行处理）。
   * - 若未显式标记 final，则当 on 为空或未定义时，也可被视作“自然终止态”。
   */
  final?: boolean;
}

/**
 * 整个状态机的配置对象。
 */
export interface MachineConfig<S extends string, E extends string> {
  /** 初始状态 */
  initial: S;
  /** 各状态的事件表与生命周期钩子 */
  states: Record<S, StateConfig<S, E>>;
}

/**
 * 单实例状态机的订阅函数签名（当前仓库仅使用了多实体版本）。
 */
export type TransitionListener<S extends string> = (
  /** 下一状态 */
  next: S,
  /** 上一状态 */
  prev: S
) => void;

/**
 * 多实体状态机的订阅函数签名：实体、下一状态、上一状态。
 */
export type MultiTransitionListener<S extends string> = (
  /** 实体 */
  entity: GameEntity,
  /** 下一状态 */
  next: S,
  /** 上一状态 */
  prev: S
) => void;

/**
 * 额外可选项：全局迁移回调等（可不传）。
 */
export interface MachineOptions<S extends string, E extends string> {
  /** 发生迁移后触发（在 onEnter/onExit 执行完毕、listeners 通知之后） */
  onTransition?: (
    /** 实体 */
    entity: GameEntity,
    /** 下一状态 */
    next: S,
    /** 上一状态 */
    prev: S,
    /** 触发迁移的事件 */
    event: E
  ) => void | Promise<void>;
}
